﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Calculate
{
    public static void RotToDest(GameObject pOwner, Vector3 vDest)
    {
        Vector2 vLook = pOwner.transform.position - vDest;

        float angle = Mathf.Atan2(vLook.y, vLook.x) * Mathf.Rad2Deg;

        //if (angle == 0.0f)
            //return;

        pOwner.transform.rotation = Quaternion.AngleAxis(angle + 90.0f, Vector3.forward);

    }

    public static float GetAngle(Vector2 OwnerPos, Vector2 DestPos)
    {
        Vector2 vLook = OwnerPos - DestPos;

        float angle = Mathf.Atan2(vLook.y, vLook.x) * Mathf.Rad2Deg;

        return angle;
    }

    public static Quaternion RotToAngle(float fAngle)
    {
        return (Quaternion.AngleAxis(fAngle, Vector3.forward));
    }

    public static void MoveToDest(GameObject pOwner, Vector3 vDest, float fSpeed)
    {
        pOwner.transform.position =
            Vector2.MoveTowards(pOwner.transform.position, vDest, fSpeed * Time.deltaTime);
    }

    public static GameObject FindThisUnit(UnitStatus ObjStatus)
    {
        GameObject Obj = null;

        for (int i = 0; i < 
            GameObject.Find("Friends").transform.childCount; ++i)
        {
            if (Obj == null)
            {
                for (int j = 0; j < GameObject.Find("Friends").transform.GetChild(i).childCount; ++j)
                {
                    if (GameObject.Find("Friends").transform.GetChild(i).GetChild(j).FindChild("Main").FindChild("Unit").GetComponent<UnitStatus>() == ObjStatus)
                    {
                        Obj = GameObject.Find("Friends").transform.GetChild(i).GetChild(j).gameObject;
                        break;
                    }
                }
            }
            else
                break;
        }

        return Obj;
    }

    public static int GetMyTileIdx(Vector2 vecPos)
    {

        //((PosY / TileSizeY * TileCountX)* 1)  + PosX / TileSizeX


        Vector3 Pos = (new Vector3(vecPos.x - GameObject.Find("DebugTile").GetComponent<Background>().m_fTileStartPosX,
             vecPos.y - GameObject.Find("DebugTile").GetComponent<Background>().m_fTileStartPosY));

        int iStartIdx0 = ((int)(System.Math.Round(Pos.y / 0.15f) * (GameObject.Find("DebugTile").GetComponent<Background>().m_iTileCountX) * -1) + (int)(System.Math.Round(Pos.x / 0.15f)));

        return iStartIdx0;
    }

    public static int GetClosestTile(Vector2 vecPos, TILE_OPTION optTile)
    {
        int iObjIdx = Calculate.GetMyTileIdx(vecPos);
        List<int> RandomingIdx = new List<int>();

        for (int i = 1; i < 999; ++i)
        {
            List<int> tmpList = Calculate.GetAllSurroundingTile(iObjIdx, i);

            for (int j = 0; j < tmpList.Count; ++j)
            {
                if (GameObject.Find("DebugTile").GetComponent<Background>().m_ListTile[tmpList[j]].GetComponent<Tile>().m_iOption == (int)optTile)
                {
                    RandomingIdx.Add(tmpList[j]);
                }
            }

            if (RandomingIdx.Count > 0)
            {
                return RandomingIdx[Random.Range(0, RandomingIdx.Count)];
            }
        }

        return 0;
    }

    public static List<int> GetPlusSurroundingTile(int TileIdx)
    {
        List<int> tmpListIdx = new List<int>();

        tmpListIdx.Add(TileIdx - GameObject.Find("DebugTile").GetComponent<Background>().m_iTileCountX);
        tmpListIdx.Add(TileIdx - 1);
        tmpListIdx.Add(TileIdx + 1);
        tmpListIdx.Add(TileIdx + GameObject.Find("DebugTile").GetComponent<Background>().m_iTileCountX);

        return tmpListIdx;
    }

    public static List<int> GetAllSurroundingTile(int TileIdx, int iDist = 1)
    {
        List<int> tmpListIdx = new List<int>();

        for (int i = -1 * iDist; i <= iDist; ++i)
        {
            for (int j = -1 * iDist; j <= iDist; ++j)
            {
                if (j == -1 * iDist || j == iDist || i == -1 * iDist || i == iDist)
                    tmpListIdx.Add(TileIdx + (GameObject.Find("DebugTile").GetComponent<Background>().m_iTileCountX * i) + j);
            }
        }

        return tmpListIdx;
    }

    public static TILE_OPTION GetMyTileOption(int iIdx)
    {
        int iTmp = GameObject.Find("DebugTile").GetComponent<Background>().m_ListTile[iIdx].GetComponent<Tile>().m_iOption;

        return (TILE_OPTION)iTmp;
    }

    public static List<int> GetSizeTileInHere(int TileIdx, Vector2 vecSize, bool bOnlyNeedSurround = false)
    {
        List<int> tmpListIdx = new List<int>();
        int tmpIdx = 0;

        for (int i = 0; i < vecSize.y; ++i)
        {
            if (i % 2 == 0)
                tmpIdx = TileIdx - (i / 2 * GameObject.Find("DebugTile").GetComponent<Background>().m_iTileCountX);
            else
                tmpIdx = TileIdx + ((i / 2 + 1) * GameObject.Find("DebugTile").GetComponent<Background>().m_iTileCountX);

            for (int j = 0; j < vecSize.x; ++j)
            {
                if (j % 2 == 0)
                    tmpIdx -= j;
                else
                    tmpIdx += j;

                if (!bOnlyNeedSurround)
                    tmpListIdx.Add(tmpIdx);
                else
                {
                    if(j == vecSize.x - 2 || j == vecSize.x - 1 || i == vecSize.y - 2 || i == vecSize.y - 1)
                        tmpListIdx.Add(tmpIdx);
                }
            }
        }

        return tmpListIdx;
    }

    public static void ChangeTileOptionInSize(int iTile, Vector2 vSize, TILE_OPTION tileOption)
    {
        List<int> iSizeIdxList = Calculate.GetSizeTileInHere(iTile, vSize);

        for (int i = 0; i < iSizeIdxList.Count; ++i)
        {
            GameObject.Find("DebugTile").GetComponent<Background>().m_ListTile[iSizeIdxList[i]].GetComponent<Tile>().m_iOption = (int)tileOption;
        }
    }

    static int CalculateClosestTileAngle(int iDist, float fStanAng, float fOwnerToTileAngle, List<int> listSurroundidx, List<GameObject> ListTile)
    {
        int iAngleIdx = 0;
        //위
        for (int i = 0; i <= (iDist * 8) / 4; ++i)
        {
            if ((135.0f - (i * fStanAng)) - (fStanAng / 2) <= fOwnerToTileAngle
                && (135.0f - (i * fStanAng)) + (fStanAng / 2) > fOwnerToTileAngle)
            {
                //Debug.Log(listSurroundidx.Count);
                if (ListTile[listSurroundidx[i]].GetComponent<Tile>().m_iOption != (int)TILE_OPTION.BLOCK 
                    && ListTile[listSurroundidx[i]].GetComponent<Tile>().m_iOption != (int)TILE_OPTION.BUILD 
                    && ListTile[listSurroundidx[i]].GetComponent<Tile>().m_iOption != (int)TILE_OPTION.IN_STRUCT)
                {
                    //Debug.Log(listSurroundidx[i]);
                    return listSurroundidx[i];
                }
            }
        }

        //오른
        for (int i = 0; (iDist * 2) + (2 * (i + 1)) < iDist * 8; ++i)
        {
            //Debug.Log((iDist * 2) + (2 * (i + 1)));
            //Debug.Log((45.0f - (i * fStanAng)) - (fStanAng / 2));
            if ((0.0f - (i * fStanAng)) - (fStanAng / 2) <= fOwnerToTileAngle
               && (0.0f - (i * fStanAng)) + (fStanAng / 2) > fOwnerToTileAngle)
            {
                if (ListTile[listSurroundidx[(iDist * 2) + (2 * (i + 1))]].GetComponent<Tile>().m_iOption != (int)TILE_OPTION.BLOCK 
                    && ListTile[listSurroundidx[(iDist * 2) + (2 * (i + 1))]].GetComponent<Tile>().m_iOption != (int)TILE_OPTION.BUILD 
                    && ListTile[listSurroundidx[(iDist * 2) + (2 * (i + 1))]].GetComponent<Tile>().m_iOption != (int)TILE_OPTION.IN_STRUCT)
                {
                    return listSurroundidx[(iDist * 2) + (2 * (i + 1))];
                }

            }
        }


        //왼
        for (int i = 0; (iDist * 2) + (2 * (i + 1)) - 1 < iDist * 5; ++i)
        {
            //Debug.Log((iDist * 2) + (2 * (i + 1)));
            //Debug.Log((45.0f - (i * fStanAng)) - (fStanAng / 2));
            float fAdjustAngle = (-180.0f + (i * fStanAng)) - (fStanAng / 2);

            if (fAdjustAngle < -180.0f)
            {
                fAdjustAngle = 180.0f + (fAdjustAngle + 180.0f);

                //Debug.Log(fAdjustAngle);
                //Debug.Log(fOwnerToTileAngle);

                if (fAdjustAngle < fOwnerToTileAngle)
                {
                    if (ListTile[listSurroundidx[(iDist * 2) + (2 * (i + 1)) - 1]].GetComponent<Tile>().m_iOption != (int)TILE_OPTION.BLOCK 
                        && ListTile[listSurroundidx[(iDist * 2) + (2 * (i + 1)) - 1]].GetComponent<Tile>().m_iOption != (int)TILE_OPTION.BUILD 
                        && ListTile[listSurroundidx[(iDist * 2) + (2 * (i + 1)) - 1]].GetComponent<Tile>().m_iOption != (int)TILE_OPTION.IN_STRUCT)
                    {
                        //Debug.Log(listSurroundidx[(iDist * 2) + (2 * (i + 1)) - 1]);
                        return listSurroundidx[(iDist * 2) + (2 * (i + 1)) - 1];
                    }

                }
            }
            else
            {
                if ((-180.0f + (i * fStanAng)) - (fStanAng / 2) <= fOwnerToTileAngle
               && (-180.0f + (i * fStanAng)) + (fStanAng / 2) > fOwnerToTileAngle)
                {
                    if (ListTile[listSurroundidx[(iDist * 2) + (2 * (i + 1)) - 1]].GetComponent<Tile>().m_iOption != (int)TILE_OPTION.BLOCK 
                        && ListTile[listSurroundidx[(iDist * 2) + (2 * (i + 1)) - 1]].GetComponent<Tile>().m_iOption != (int)TILE_OPTION.BUILD 
                        && ListTile[listSurroundidx[(iDist * 2) + (2 * (i + 1)) - 1]].GetComponent<Tile>().m_iOption != (int)TILE_OPTION.IN_STRUCT)
                    {

                        return listSurroundidx[(iDist * 2) + (2 * (i + 1)) - 1];
                    }

                }
            }


        }

        //아래
        for (int i = 0; (iDist * 6 - 1) + i < iDist * 8; ++i)
        {
            //Debug.Log((-135.0f - (i * fStanAng)) - (fStanAng / 2));

            if ((-135.0f + (i * fStanAng)) - (fStanAng / 2) <= fOwnerToTileAngle
                && (-135.0f + (i * fStanAng)) + (fStanAng / 2) > fOwnerToTileAngle)
            {
                if (ListTile[listSurroundidx[(iDist * 6 - 1) + i]].GetComponent<Tile>().m_iOption != (int)TILE_OPTION.BLOCK 
                    && ListTile[listSurroundidx[(iDist * 6 - 1) + i]].GetComponent<Tile>().m_iOption != (int)TILE_OPTION.BUILD
                    && ListTile[listSurroundidx[(iDist * 6 - 1) + i]].GetComponent<Tile>().m_iOption != (int)TILE_OPTION.IN_STRUCT)
                {
                    //Debug.Log(listSurroundidx[i]);
                    return listSurroundidx[(iDist * 6 - 1) + i];
                }
            }
        }

        return iAngleIdx;
    }

    public static int CalculateTileAngle(int iEnd, float fOwnerToTileAngle, List<GameObject> ListTile)
    {
        int iDist = 1;
        float fStanAng = 45.0f;
        int iAngleIndex = 0;

        List<int> listSurroundidx = Calculate.GetAllSurroundingTile(iEnd, iDist);
        List<float> listAngle = new List<float>();


        

        if (CalculateClosestTileAngle(iDist, fStanAng, fOwnerToTileAngle, listSurroundidx, ListTile) != 0)
            return CalculateClosestTileAngle(iDist, fStanAng, fOwnerToTileAngle, listSurroundidx, ListTile);

        while(true)
        {
            fStanAng /= iDist;

            for (int i = 0; i < listSurroundidx.Count - 1; ++i)
            {
                if (i % 2 == 0)
                {
                    if (fOwnerToTileAngle - (fStanAng * (i / 2 + 1)) <= -180.0f)
                        listAngle.Add(fOwnerToTileAngle - (fStanAng * (i / 2 + 1)) + 360.0f);
                    else
                        listAngle.Add(fOwnerToTileAngle - (fStanAng * (i / 2 + 1)));
                }
                else
                {
                    if (fOwnerToTileAngle + (fStanAng * (i / 2 + 1)) > 180.0f)
                        listAngle.Add(fOwnerToTileAngle + (fStanAng * (i / 2 + 1)) - 360.0f);
                    else
                        listAngle.Add(fOwnerToTileAngle + (fStanAng * (i / 2 + 1)));
                }
            }

            for (int i = 0; i < listAngle.Count; ++i)
            {
                if (CalculateClosestTileAngle(iDist, fStanAng, listAngle[i], listSurroundidx, ListTile) != 0)
                {
                    return CalculateClosestTileAngle(iDist, fStanAng, listAngle[i], listSurroundidx, ListTile);
                }
            }

            iDist += 1;
            listAngle.Clear();
            listSurroundidx.Clear();
            listSurroundidx = Calculate.GetAllSurroundingTile(iEnd, iDist);
        }
        



        //iAngleIndex = (int)(fOwnerToTileAngle / fStanAng);

        //++iDist;

        return 0;

    }

    public static bool AStarStart(GameObject ObjOwner, Vector2 vecDest, ref List<int> BestList, int m_iPrevTIleIdx, int m_iPrevTileOption)
    {
        ObjOwner.GetComponent<AStar>().AStarStart(Calculate.GetMyTileIdx(ObjOwner.transform.position), Calculate.GetMyTileIdx(vecDest));
        BestList = ObjOwner.GetComponent<AStar>().GetBestList();

        //End
        if (BestList != null)
        {
            //Tile Change
            List<GameObject> ListTile = GameObject.Find("DebugTile").GetComponent<Background>().m_ListTile;

            if (ListTile[m_iPrevTIleIdx].GetComponent<Tile>().m_iOption == (int)TILE_OPTION.BLOCK)
                ListTile[m_iPrevTIleIdx].GetComponent<Tile>().m_iOption = m_iPrevTileOption;

            return false;
        }

        return true;
    }

    public static bool Acuur_Calculate(int iAcuurStat /*Personal + Weapon*/)
    {
        //1~10범위안에 랜덤값 돌림 

        //if(스탯 > 랜덤값)
        //명중
        //else
        //빗맞음


        int iAcuurFlag = Random.Range(0, 20);

        if (iAcuurStat >= iAcuurFlag)
            return true;
        else
            return false;

    }

    public static GameObject FindThisTile(int iTileIdx)
    {
        return GameObject.Find("DebugTile").GetComponent<Background>().m_ListTile[iTileIdx];
    }

    public static Vector3 GetMousePos()
    {
        return Camera.main.ScreenToWorldPoint(Input.mousePosition);
    }

}

